/* Copyright (C) 2005, 2006 by Daniel Gheorghian
 All rights reserved
 
 Use and distribute freely, except: don't remove my name from the source or documentation 
 (don't take credit for my work), mark your changes (don't get me blamed for your possible bugs),
 don't alter or remove this notice.
 
 No warrantee of any kind, express or implied, is included with this software; use at your
 own risk, responsibility for damages (if any) to anyone resulting from the use of this
 software rests entirely with the user.
 
 Send bug reports, bug fixes, enhancements, requests, flames, etc., and I'll try to keep 
 a version up to date.  I can be reached at: daniel.gheorghian@gmail.com
*/


package com.ds.components.bars;

import com.ds.components.interactors.Interactor;
import com.ds.components.interactors.InteractorEvent;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Map;
import java.util.TreeMap;

public class ElbowBar extends JPanel
{
	public static final int TOP = 1;
	public static final int BOTTOM = 2;
	public static final int LEFT_CONNECTOR = 3;
	public static final int RIGHT_CONNECTOR = 4;
	public static final int BUTTON_HGAP = 20;
	private static final int TEXT_HGAP = 20;

	//todo replace all this with a renderer for the background
	private Paint backgoundPaint = null;
	private Paint brighterBackgroundPaint = null;
	private Color background1 = new Color( 250, 189, 96 );
	private Color background2 = new Color( 240, 226, 161 );
	private int barLayout;
	private int connectorPosition;
	private int borderSize;
	private int connectorSize;
	private int leftSpace;
	private int rightSpace;

	private Map<String, Dimension> buttons;
	private Map<String, Interactor> buttonsInteractors;
	private Map<String, Boolean> buttonsVisibility;
	private Interactor textInteractor;
	private String text;
	private Color textBackground;

	public ElbowBar()
	{
		this.barLayout = 1;
		this.borderSize = 5;
		this.connectorSize = 10;
		this.connectorPosition = ElbowBar.LEFT_CONNECTOR;
		this.buttons = new TreeMap<String, Dimension>();
		this.buttonsInteractors = new TreeMap<String, Interactor>();
		this.buttonsVisibility = new TreeMap<String, Boolean>();
		this.textBackground = null;
		this.text = "";
		this.leftSpace = 150;
		this.rightSpace = 100;

		this.addMouseListener( new ButtonsListener() );
	}

	public void paint( Graphics g )
	{
		int w = this.getWidth();
		int h = this.getHeight();
		if( backgoundPaint == null )
		{
			this.backgoundPaint = new GradientPaint( w / 2, 0, background1, w / 2, h, background2 );
		}

		if( brighterBackgroundPaint == null )
		{
			this.brighterBackgroundPaint = new GradientPaint( w / 2, 0, background1.brighter(),
			                                                  w / 2, h, background2.brighter() );
		}

		Graphics2D g2D = ( Graphics2D ) g;
		g2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );

		g2D.setPaint( this.getBackground() );
		g2D.fillRect( 0, 0, w, h );

		g2D.setPaint( backgoundPaint );

		switch( barLayout )
		{
			case TOP:
				switch( connectorPosition )
				{
					case LEFT_CONNECTOR:
						g2D.fillRoundRect( borderSize, borderSize, w + 20, h + 25, 50, 50 );
						g2D.setColor( Color.black );
						g2D.fillRoundRect( borderSize + connectorSize, h - 15, w, 80, 30, 30 );
						g2D.fillRect( w - borderSize, 0, borderSize, h );
						break;
					case RIGHT_CONNECTOR:
						g2D.fillRoundRect( -20, borderSize, w + 20 - borderSize, h + 25, 50, 50 );
						g2D.setColor( Color.black );
						g2D.fillRoundRect( -20, h - 15, w - borderSize - connectorSize + 20, 80, 30, 30 );
						g2D.fillRect( 0, 0, borderSize, h );
						break;
				}
				break;
			case BOTTOM:
				switch( connectorPosition )
				{
					case LEFT_CONNECTOR:
						g2D.fillRoundRect( borderSize, -25, w + 25, h - borderSize + 25, 50, 50 );
						g2D.setColor( Color.black );
						g2D.fillRoundRect( borderSize + connectorSize, -25, w, 40, 30, 30 );
						g2D.fillRect( w - borderSize, 0, borderSize, h );
						break;
					case RIGHT_CONNECTOR:
						g2D.fillRoundRect( -20, -20, w + 20 - borderSize, h + 20 - borderSize, 50, 50 );
						g2D.setColor( Color.black );
						g2D.fillRoundRect( -25, -25, w - borderSize - connectorSize + 25, 40, 30, 30 );
						g2D.fillRect( 0, 0, borderSize, h );
						break;
				}
				break;
		}

		if( this.buttons.size() != 0 )
		{
			g2D.setFont( this.getFont() );
			g2D.setStroke( new BasicStroke( 5.0F ) );
			Dimension size;
			int xCoord = leftSpace;
			int yCoord = this.getHeight() - 20;

			for( String name : this.buttons.keySet() )
			{
				if( !this.buttonsVisibility.get( name ) )
				{
					continue;
				}

				size = this.buttons.get( name );
				if( size.width == 0 )
				{
					size = new Dimension();
					size.width = g2D.getFontMetrics( g2D.getFont() ).stringWidth( name ) + 2 * BUTTON_HGAP;
					size.height = this.getHeight() - 20;
					this.buttons.put( name, size );
				}

				g2D.setColor( Color.black );
				g2D.drawLine( xCoord - 5, 0, xCoord - 5, this.getHeight() );

				g2D.setColor( this.getForeground() );
				g2D.drawString( name, xCoord, yCoord );

				xCoord += size.width + 5;
			}

			if( this.connectorPosition == RIGHT_CONNECTOR )
			{
				g2D.setColor( Color.black );
				g2D.drawLine( this.getWidth() - connectorSize - 18, 0, this.getWidth() - connectorSize - 18, this.getHeight() );
			}
			else
			{
				g2D.setColor( Color.black );
				g2D.drawLine( xCoord - 5, 0, xCoord - 5, this.getHeight() );
			}
		}
		else
		{
			if( !text.equals( "" ) )
			{
				g2D.setFont( this.getFont() );
				int textSize = g2D.getFontMetrics( this.getFont() ).stringWidth( text ) + 2 * TEXT_HGAP;
				int xCoord = this.getWidth() - rightSpace - textSize;
				int yCoord = this.getHeight() - 20;

				if( textBackground != null )
				{
					g2D.setColor( textBackground );
					g2D.fillRect( xCoord, 0, textSize, this.getHeight() );
				}

				g2D.setColor( this.getForeground() );
				g2D.drawString( text, xCoord + TEXT_HGAP, yCoord );
			}
		}
	}

	public void flashButton( String name, Rectangle buttonArea )
	{
		if( this.buttons.get( name ) != null )
		{
			Graphics2D g2D = ( Graphics2D ) this.getGraphics();
			g2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );

			g2D.setPaint( this.brighterBackgroundPaint );
			g2D.fillRect( buttonArea.x, buttonArea.y, buttonArea.width, buttonArea.height );

			g2D.setColor( this.getForeground() );
			g2D.drawString( name, buttonArea.x + 2, this.getHeight() - 20 );

			try
			{
				Thread.sleep( 20 );
			}
			catch( Exception ex )
			{
				ex.printStackTrace();
			}

			g2D.setPaint( this.backgoundPaint );
			g2D.fillRect( buttonArea.x, buttonArea.y, buttonArea.width, buttonArea.height );

			g2D.setColor( this.getForeground() );
			g2D.drawString( name, buttonArea.x + 2, this.getHeight() - 20 );
		}
	}

	public int getBarLayout()
	{
		return barLayout;
	}

	public void setBarLayout( int barLayout )
	{
		this.barLayout = barLayout;
	}

	public int getBorderSize()
	{
		return borderSize;
	}

	public void setBorderSize( int borderSize )
	{
		this.borderSize = borderSize;
	}

	public int getConnectorSize()
	{
		return connectorSize;
	}

	public void setConnectorSize( int connectorSize )
	{
		this.connectorSize = connectorSize;
	}

	public int getConnectorPosition()
	{
		return connectorPosition;
	}

	public void setConnectorPosition( int connectorPosition )
	{
		this.connectorPosition = connectorPosition;
	}

	public void addButton( String name )
	{
		addButton( name, new Dimension(), null );
	}

	public void addButton( String name, Dimension size )
	{
		addButton( name, size, null );
	}

	public void addButton( String name, Interactor interactor )
	{
		addButton( name, new Dimension(), interactor );
	}

	public void addButton( String name, Dimension size, Interactor interactor )
	{
		this.buttons.put( name, size );
		setInteractor( name, interactor );
		setVisibility( name, true );
	}

	public void setVisibility( String name, boolean visibility )
	{
		this.buttonsVisibility.put( name, visibility );
	}

	public boolean getVisibility( String name )
	{
		return this.buttonsVisibility.get( name );
	}

	public void setInteractor( String name, Interactor interactor )
	{
		this.buttonsInteractors.put( name, interactor );
	}

	public String getText()
	{
		return text;
	}

	public void setText( String text )
	{
		this.text = text;
	}

	public Color getTextBackground()
	{
		return textBackground;
	}

	public void setTextBackground( Color textBackground )
	{
		this.textBackground = textBackground;
	}

	public int getLeftSpace()
	{
		return leftSpace;
	}

	public void setLeftSpace( int leftSpace )
	{
		this.leftSpace = leftSpace;
	}

	public int getRightSpace()
	{
		return rightSpace;
	}

	public void setRightSpace( int rightSpace )
	{
		this.rightSpace = rightSpace;
	}

	private class ButtonsListener extends MouseAdapter
	{
		public void mouseClicked( MouseEvent e )
		{
			int xCoord = leftSpace;
			Dimension size;
			Rectangle buttonArea;
			Interactor interactor;

			for( String key : buttons.keySet() )
			{
				if( !buttonsVisibility.get( key ) )
				{
					continue;
				}
				size = buttons.get( key );
				buttonArea = new Rectangle( new Point( xCoord - 2, 5 ), size );

				if( buttonArea.contains( e.getPoint() ) )
				{
					interactor = buttonsInteractors.get( key );
					if( interactor != null && interactor.getActivationMethodType() == Interactor.ON_MOUSE_CLICKED )
					{
						flashButton( key, buttonArea );
						interactor.onActivation( new InteractorEvent( key ) );
					}
					return;
				}

				xCoord += size.width + 5;
			}

			int textSize = getFontMetrics( getFont() ).stringWidth( text ) + 2 * TEXT_HGAP;
			xCoord = getWidth() - rightSpace - textSize;

			if( new Rectangle( new Point( xCoord, 0 ), new Dimension( textSize, getHeight() ) ).contains( e.getPoint() )
			    && textInteractor != null && textInteractor.getActivationMethodType() == Interactor.ON_MOUSE_CLICKED )
			{
				textInteractor.onActivation( new InteractorEvent( text ) );
			}
		}
	}

	/**
	 * @param textInteractor the textInteractor to set
	 */
	public void setTextInteractor( Interactor textInteractor )
	{
		this.textInteractor = textInteractor;
	}
}
